package com.group9.handinhand.dao.model;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.apache.commons.lang.ArrayUtils;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import com.group9.handinhand.service.so.CommunityEnums.CommunityPrivacy;
import com.group9.handinhand.service.so.CommunityEnums.RequiredPermissionToSubscribe;
import com.group9.handinhand.service.so.CommunitySO;

@Entity
@Table(name = "COMMUNITY")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Community extends AbstractBaseModel {
	
	private static final long serialVersionUID = 1L;

	@Column(name = "NAME", nullable = false)
	private String name;
	
	@Column(name = "DESCRIPTION")
	private String description;
	
	@OneToOne
	@JoinColumn(name = "CATEGORY_ID")
	private CommunityCategory category;
	
	@Enumerated(EnumType.STRING)
	@Column(name = "PRIVACY", nullable = false)
	private CommunityPrivacy privacy;
	
	@Enumerated(EnumType.STRING)
	@Column(name = "PERMISSION", nullable = false)
	private RequiredPermissionToSubscribe permission;
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(name = "COMMUNITY_MODERATOR", joinColumns = @JoinColumn(name = "COMMUNITY_ID", nullable = false), 
	inverseJoinColumns = @JoinColumn(name = "USER_ID", nullable = false), 
	uniqueConstraints = @UniqueConstraint(columnNames = {"USER_ID", "COMMUNITY_ID" }))
	private Set<User> moderators = new HashSet<User>();
	
	@OneToMany(mappedBy = "community", fetch = FetchType.LAZY)
	private Set<CommunityPost> posts = new HashSet<CommunityPost>();
	
	@OneToMany(mappedBy = "community", fetch = FetchType.LAZY)
	private Set<Event> events = new HashSet<Event>();
	
	@OneToMany(mappedBy = "community", fetch = FetchType.LAZY)
	private Set<Request> requests = new HashSet<Request>();
	
	@OneToMany(mappedBy = "community", fetch = FetchType.LAZY)
	private Set<Offer> offers = new HashSet<Offer>();
	
	@OneToMany(mappedBy = "community", fetch = FetchType.LAZY)
	private Set<CommunityMember> members = new HashSet<CommunityMember>();
	
	public CommunitySO convertToServiceObject(String... ignoreProperties) {
		CommunitySO so = (CommunitySO) convert(new CommunitySO(), 
			(String[]) ArrayUtils.addAll(ignoreProperties,new String[]{"moderators", "posts", "events","requests","offers","members"}));
		if( ! Arrays.asList(ignoreProperties).contains("moderators"))
			for (User user : moderators) {
				so.getModerators().add(user.convertToServiceObject(new String[]{"socialUsers"}));
			}
		if (!Arrays.asList(ignoreProperties).contains("posts"))
			for (CommunityPost post : posts) {
				so.getPosts().add(post.convertToServiceObject());
			}
		if (!Arrays.asList(ignoreProperties).contains("events"))
			for (Event event : events) {
				so.getEvents().add(event.convertToServiceObject());
			}
		if (!Arrays.asList(ignoreProperties).contains("requests"))
			for (Request request : requests) {
				so.getRequests().add(request.convertToServiceObject());
			}
		if (!Arrays.asList(ignoreProperties).contains("offers"))
			for (Offer offer : offers) {
				so.getOffers().add(offer.convertToServiceObject());
			}
		if (!Arrays.asList(ignoreProperties).contains("members"))
			for (CommunityMember member : members) {
				so.getMembers().add(member.convertToServiceObject());
			}

		return so;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public CommunityCategory getCategory() {
		return category;
	}

	public void setCategory(CommunityCategory category) {
		this.category = category;
	}

	public CommunityPrivacy getPrivacy() {
		return privacy;
	}

	public void setPrivacy(CommunityPrivacy privacy) {
		this.privacy = privacy;
	}

	public RequiredPermissionToSubscribe getPermission() {
		return permission;
	}

	public void setPermission(RequiredPermissionToSubscribe permission) {
		this.permission = permission;
	}

	public Set<User> getModerators() {
		return moderators;
	}

	public void setModerators(Set<User> moderators) {
		this.moderators = moderators;
	}

	public Set<CommunityPost> getPosts() {
		return posts;
	}

	public void setPosts(Set<CommunityPost> posts) {
		this.posts = posts;
	}

	public Set<Event> getEvents() {
		return events;
	}

	public void setEvents(Set<Event> events) {
		this.events = events;
	}

	public Set<Request> getRequests() {
		return requests;
	}

	public void setRequests(Set<Request> requests) {
		this.requests = requests;
	}

	public Set<Offer> getOffers() {
		return offers;
	}

	public void setOffers(Set<Offer> offers) {
		this.offers = offers;
	}

	public Set<CommunityMember> getMembers() {
		return members;
	}

	public void setMembers(Set<CommunityMember> members) {
		this.members = members;
	}

	@Override
	public String toString() {
		return "Community [name=" + name + ", description=" + description
				+ ", category=" + category + ", privacy=" + privacy
				+ ", permission=" + permission + ", moderators=" + moderators
				+ ", posts=" + posts + ", events=" + events + ", requests="
				+ requests + ", offers=" + offers + ", members=" + members
				+ "]";
	}

}
